package com.google.code.hibernate.rest.representation.json;
import static com.google.code.hibernate.rest.internal.InternalPreconditions.checkNotNull;

import com.google.code.hibernate.rest.EntityManager;
import com.google.code.hibernate.rest.representation.AbstractXStreamPepresentor;
import com.google.code.hibernate.rest.representation.XStreamBuilder;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.ConverterLookup;
import com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy;
import com.thoughtworks.xstream.core.TreeMarshaller;
import com.thoughtworks.xstream.core.TreeUnmarshaller;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.mapper.Mapper;

/**
 * 
 * @author wangzijian
 * 
 */
public class JSONRepresentor extends AbstractXStreamPepresentor {

	public static final String HREF = "href";
	private static final String CONTENT_TYPE = "application/json";

	private final EntityManager entityManager;
	private final XStream xStream;

	public JSONRepresentor(EntityManager entityManager) {
		this.entityManager = checkNotNull(entityManager, "entityManager");
		this.xStream = new XStreamBuilder()
			.driver(new JettisonMappedXmlDriver())
			.strategy(new EntityMarshallingStrategy())
			.alias(entityManager.getSimpleEntityNames())
			.build();
	}

	@Override
	protected XStream xStream() {
		return xStream;
	}

	@Override
	public String getContentType() {
		return CONTENT_TYPE;
	}

	private class EntityMarshallingStrategy extends AbstractTreeMarshallingStrategy {

		@Override
		protected TreeUnmarshaller createUnmarshallingContext(Object root, HierarchicalStreamReader reader, ConverterLookup converterLookup, Mapper mapper) {
			return new EntityJSONUnmarshaller(root, reader, converterLookup, mapper, entityManager);
		}

		@Override
		protected TreeMarshaller createMarshallingContext(HierarchicalStreamWriter writer, ConverterLookup converterLookup, Mapper mapper) {
			return new EntityJSONMarshaller(writer, converterLookup, mapper, entityManager);
		}
	}
}
